package net.ming616.nlp.owl.service.impl;

import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import net.ming616.nlp.owl.service.OntologyMaintainManager;

import org.semanticweb.owlapi.io.OWLXMLOntologyFormat;
import org.semanticweb.owlapi.model.AddAxiom;
import org.semanticweb.owlapi.model.IRI;
import org.semanticweb.owlapi.model.OWLAxiom;
import org.semanticweb.owlapi.model.OWLClass;
import org.semanticweb.owlapi.model.OWLClassAssertionAxiom;
import org.semanticweb.owlapi.model.OWLClassExpression;
import org.semanticweb.owlapi.model.OWLDataProperty;
import org.semanticweb.owlapi.model.OWLDataPropertyAssertionAxiom;
import org.semanticweb.owlapi.model.OWLIndividual;
import org.semanticweb.owlapi.model.OWLLiteral;
import org.semanticweb.owlapi.model.OWLNamedIndividual;
import org.semanticweb.owlapi.model.OWLObjectProperty;
import org.semanticweb.owlapi.model.OWLObjectPropertyAssertionAxiom;
import org.semanticweb.owlapi.model.OWLObjectPropertyExpression;
import org.semanticweb.owlapi.model.OWLOntologyChange;
import org.semanticweb.owlapi.model.OWLOntologyFormat;
import org.semanticweb.owlapi.model.OWLOntologyStorageException;
import org.springframework.stereotype.Service;

@Service(value = "ontologyMaintainManager")
public class OntologyMaintainManagerImpl extends BaseOWLManagerImpl implements
		OntologyMaintainManager {

	public OWLNamedIndividual createIndividual(String individualName) {
		// individualName = StringUtils.replace(individualName, " ", "_");
		OWLNamedIndividual individual = this.dataFactory
				.getOWLNamedIndividual(IRI.create(this.baseURI + "#"
						+ individualName));
		return individual;
	}

	public void createIndividualOfClass(OWLClass owlcls,
			OWLIndividual owlIndividual) {
		OWLClassAssertionAxiom axiom = this.dataFactory
				.getOWLClassAssertionAxiom(owlcls, owlIndividual);
		ontology.getOWLOntologyManager().addAxiom(ontology, axiom);
	}

	public OWLClass createOWLClass(String conceptName) {
		return this.dataFactory.getOWLClass(IRI.create(this.baseURI + "#"
				+ conceptName));
	}

	public OWLObjectProperty createObjectProperty(String propertyName) {
		OWLObjectProperty objectProperty = this.dataFactory
				.getOWLObjectProperty(IRI.create(this.baseURI + "#"
						+ propertyName));
		return objectProperty;
	}

	public OWLDataProperty createDataProperty(String propertyName) {
		OWLDataProperty dataProperty = dataFactory.getOWLDataProperty(IRI
				.create("#" + propertyName));
		return dataProperty;
	}

	public void createRelationOfIndividuals(OWLObjectProperty property,
			OWLIndividual owlIndividual1, OWLIndividual owlIndivididual2) {
		OWLObjectPropertyAssertionAxiom assertion = this.dataFactory
				.getOWLObjectPropertyAssertionAxiom(property, owlIndividual1,
						owlIndivididual2);
		AddAxiom addAxiomChange = new AddAxiom(ontology, assertion);
		this.owlManager.applyChange(addAxiomChange);
	}

	public List<OWLOntologyChange> createRelationForIndividualAndData(
			OWLIndividual individual, String dataPropertyName,
			String dataPropertyType, String dataPropertyValue) {
		OWLDataProperty dataProperty = this
				.createDataProperty(dataPropertyName);
		OWLLiteral value = dataFactory.getOWLLiteral(dataPropertyValue);
		OWLDataPropertyAssertionAxiom axiom = dataFactory
				.getOWLDataPropertyAssertionAxiom(dataProperty, individual,
						value);
		List<OWLOntologyChange> result = this.addAxiom(axiom);
		return result;

	}

	public void createSubClassRelation(OWLClass clsChild, OWLClass clsParent) {
		OWLAxiom axiom = this.dataFactory.getOWLSubClassOfAxiom(clsChild,
				clsParent);
		AddAxiom addAxiom = new AddAxiom(ontology, axiom);
		this.owlManager.applyChange(addAxiom);
	}

	public Set<OWLClass> getClassesOfIndividual(OWLIndividual individual) {
		Set<OWLClass> classes = new HashSet<OWLClass>();
		Set<OWLClassAssertionAxiom> set = ontology
				.getClassAssertionAxioms(individual);
		Iterator<OWLClassAssertionAxiom> it = set.iterator();
		while (it.hasNext()) {
			OWLClassAssertionAxiom oWLClassAssertionAxiom = it.next();
			OWLClass cls = oWLClassAssertionAxiom.getClassExpression()
					.asOWLClass();
			classes.add(cls);
		}
		return classes;
	}

	public Set<OWLIndividual> getIndividualsOfClass(OWLClass owlcls) {
		return owlcls.getIndividuals(ontology);
	}

	public Map<OWLObjectPropertyExpression, Set<OWLIndividual>> getObjectPropertyValues(
			OWLNamedIndividual owlIndi) {
		return owlIndi.getObjectPropertyValues(ontology);
	}

	public Set<OWLClassExpression> getSubClasses(OWLClass owlcls) {
		return owlcls.getSubClasses(ontology);
	}

	public void saveOntology() {
		OWLOntologyFormat format = this.owlManager.getOntologyFormat(ontology);
		System.out.println(" format: " + format);
		OWLXMLOntologyFormat owlxmlFormat = new OWLXMLOntologyFormat();
		if (format.isPrefixOWLOntologyFormat()) {
			owlxmlFormat.copyPrefixesFrom(format.asPrefixOWLOntologyFormat());
		}
		try {
			this.owlManager.saveOntology(ontology, owlxmlFormat,
					IRI.create(this.owlFile.toURI()));
		} catch (OWLOntologyStorageException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public List<OWLOntologyChange> addAxiom(OWLAxiom axiom) {
		List<OWLOntologyChange> result = this.owlManager.addAxiom(ontology,
				axiom);
		return result;
	}

}
